; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; REQUIRES: asserts
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes=loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require<domtree>,loop(loop-simplifycfg)' -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s
; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes=loop-simplifycfg -verify-memoryssa -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:1"

; Make sure that we can eliminate a provably dead backedge.
define i32 @dead_backedge_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_backedge_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_BE:%.*]], [[HEADER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[I_1:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I_1]], 100
; CHECK-NEXT:    br i1 [[CMP1]], label [[HEADER_BACKEDGE]], label [[DEAD_BACKEDGE:%.*]]
; CHECK:       header.backedge:
; CHECK-NEXT:    [[I_BE]] = phi i32 [ [[I_1]], [[HEADER]] ], [ [[I_2:%.*]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       dead_backedge:
; CHECK-NEXT:    [[I_2]] = add i32 [[I_1]], 10
; CHECK-NEXT:    br i1 false, label [[HEADER_BACKEDGE]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_2_LCSSA:%.*]] = phi i32 [ [[I_2]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_2_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.1, %header], [%i.2, %dead_backedge]
  %i.1 = add i32 %i, 1
  %cmp1 = icmp slt i32 %i.1, 100
  br i1 %cmp1, label %header, label %dead_backedge

dead_backedge:
  %i.2 = add i32 %i.1, 10
  br i1 false, label %header, label %exit

exit:
  ret i32 %i.2
}

; Make sure that we can eliminate a provably dead backedge with switch.
define i32 @dead_backedge_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_backedge_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_BE:%.*]], [[HEADER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[I_1:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[I_1]], 100
; CHECK-NEXT:    br i1 [[CMP1]], label [[HEADER_BACKEDGE]], label [[DEAD_BACKEDGE:%.*]]
; CHECK:       header.backedge:
; CHECK-NEXT:    [[I_BE]] = phi i32 [ [[I_1]], [[HEADER]] ], [ [[I_2:%.*]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       dead_backedge:
; CHECK-NEXT:    [[I_2]] = add i32 [[I_1]], 10
; CHECK-NEXT:    switch i32 1, label [[EXIT:%.*]] [
; CHECK-NEXT:    i32 0, label [[HEADER_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       exit:
; CHECK-NEXT:    [[I_2_LCSSA:%.*]] = phi i32 [ [[I_2]], [[DEAD_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_2_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.1, %header], [%i.2, %dead_backedge]
  %i.1 = add i32 %i, 1
  %cmp1 = icmp slt i32 %i.1, 100
  br i1 %cmp1, label %header, label %dead_backedge

dead_backedge:
  %i.2 = add i32 %i.1, 10
  switch i32 1, label %exit [i32 0, label %header]

exit:
  ret i32 %i.2
}

; Check that we can eliminate a triangle.
define i32 @dead_block_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can eliminate dead branches of a switch.
define i32 @dead_block_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit
exit:
  ret i32 %i.inc
}

; Check that we can eliminate several dead blocks.
define i32 @dead_block_propogate_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_propogate_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %dummy

dummy:
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can eliminate several blocks while removing a switch.
define i32 @dead_block_propogate_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_block_propogate_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]

dead:
  %i.2 = add i32 %i, 1
  br label %dummy

dummy:
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we preserve static reachibility of a dead exit block while deleting
; a branch.
define i32 @dead_exit_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[DEAD:%.*]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK:       dead:
; CHECK-NEXT:    br label [[DUMMY:%.*]]
; CHECK:       dummy:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       exit.loopexit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ poison, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT:    ret i32 [[I_1]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  br label %dummy

dummy:
  br label %exit

backedge:
  %i.inc = add i32 %i, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  %i.1 = phi i32 [%i.inc, %backedge], [%i, %dummy]
  ret i32 %i.1
}

; Check that we preserve static reachibility of a dead exit block while deleting
; a switch.
define i32 @dead_exit_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[DEAD:%.*]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK:       dead:
; CHECK-NEXT:    br label [[DUMMY:%.*]]
; CHECK:       dummy:
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       exit.loopexit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ poison, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT:    ret i32 [[I_1]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]

dead:
  br label %dummy

dummy:
  br label %exit

backedge:
  %i.inc = add i32 %i, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  %i.1 = phi i32 [%i.inc, %backedge], [%i, %dummy]
  ret i32 %i.1
}

; Check that we can completely eliminate the current loop, branch case.
define i32 @dead_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_loop_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 false, label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %dummy

dummy:
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 false, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can completely eliminate the current loop, switch case.
define i32 @dead_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_loop_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 1, label [[DEAD:%.*]] [
; CHECK-NEXT:    i32 0, label [[DEAD]]
; CHECK-NEXT:    i32 1, label [[BACKEDGE]]
; CHECK-NEXT:    i32 2, label [[DEAD]]
; CHECK-NEXT:    ]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 false, label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header
header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]
dead:
  %i.2 = add i32 %i, 1
  br label %dummy

dummy:
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 false, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can delete a dead inner loop entirely.
define i32 @dead_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_sub_loop_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[EXIT_A:%.*]] ]
; CHECK-NEXT:    br label [[LIVE_LOOP:%.*]]
; CHECK:       live_loop:
; CHECK-NEXT:    [[A:%.*]] = phi i32 [ 0, [[HEADER]] ], [ [[A_INC:%.*]], [[LIVE_LOOP]] ]
; CHECK-NEXT:    [[A_INC]] = add i32 [[A]], 1
; CHECK-NEXT:    [[CMP_A:%.*]] = icmp slt i32 [[A_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_A]], label [[LIVE_LOOP]], label [[EXIT_A]]
; CHECK:       exit.a:
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[EXIT_A]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %live_preheader, label %dead_preheader

live_preheader:
  br label %live_loop

live_loop:
  %a = phi i32 [0, %live_preheader], [%a.inc, %live_loop]
  %a.inc = add i32 %a, 1
  %cmp.a = icmp slt i32 %a.inc, %end
  br i1 %cmp.a, label %live_loop, label %exit.a

exit.a:
  br label %backedge

dead_preheader:
  br label %dead_loop

dead_loop:
  %b = phi i32 [0, %dead_preheader], [%b.inc, %dead_loop]
  %b.inc = add i32 %b, 1
  %cmp.b = icmp slt i32 %b.inc, %end
  br i1 %cmp.b, label %dead_loop, label %exit.b

exit.b:
  br label %backedge

backedge:
  %i.inc = add i32 %i, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @dead_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_sub_loop_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[EXIT_A:%.*]] ]
; CHECK-NEXT:    br label [[LIVE_LOOP:%.*]]
; CHECK:       live_loop:
; CHECK-NEXT:    [[A:%.*]] = phi i32 [ 0, [[HEADER]] ], [ [[A_INC:%.*]], [[LIVE_LOOP]] ]
; CHECK-NEXT:    [[A_INC]] = add i32 [[A]], 1
; CHECK-NEXT:    [[CMP_A:%.*]] = icmp slt i32 [[A_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_A]], label [[LIVE_LOOP]], label [[EXIT_A]]
; CHECK:       exit.a:
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[EXIT_A]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead_preheader [i32 0, label %dead_preheader
  i32 1, label %live_preheader
  i32 2, label %dead_preheader]

live_preheader:
  br label %live_loop

live_loop:
  %a = phi i32 [0, %live_preheader], [%a.inc, %live_loop]
  %a.inc = add i32 %a, 1
  %cmp.a = icmp slt i32 %a.inc, %end
  br i1 %cmp.a, label %live_loop, label %exit.a

exit.a:
  br label %backedge

dead_preheader:
  br label %dead_loop

dead_loop:
  %b = phi i32 [0, %dead_preheader], [%b.inc, %dead_loop]
  %b.inc = add i32 %b, 1
  %cmp.b = icmp slt i32 %b.inc, %end
  br i1 %cmp.b, label %dead_loop, label %exit.b

exit.b:
  br label %backedge

backedge:
  %i.inc = add i32 %i, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we preserve static reachability of an exit block even if we prove
; that the loop is infinite. Branch case.
define i32 @inf_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[EXIT:%.*]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 poison
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %dummy

dummy:
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 true, label %header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @inf_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[EXIT:%.*]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       exit:
; CHECK-NEXT:    ret i32 poison
;
preheader:
  br label %header
header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]
dead:
  %i.2 = add i32 %i, 1
  br label %dummy
dummy:
  br label %backedge
backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dummy]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 true, label %header, label %exit
exit:
  ret i32 %i.inc
}

; Check that when the block is not actually dead, we don't remove it.
define i32 @live_block_test_branch_loop(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_branch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK:       check:
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       live:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 %c, label %check, label %live

check:
  br i1 true, label %backedge, label %live

live:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %check], [%i.2, %live]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that when the block is not actually dead, we don't remove it. Version
; with Phi node.
define i32 @live_block_test_branch_loop_phis(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_branch_loop_phis(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK:       check:
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       live:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 %c, label %check, label %live

check:
  br i1 true, label %backedge, label %live

live:
  %phi = phi i32 [ 1, %header ], [ -1, %check ]
  %i.2 = add i32 %i, %phi
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %check], [%i.2, %live]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @live_block_test_switch_loop(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_switch_loop(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK:       check:
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       live:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 %c, label %check, label %live

check:
  switch i32 1, label %live [i32 0, label %live
  i32 1, label %backedge
  i32 2, label %live]

live:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %check], [%i.2, %live]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @live_block_test_switch_loop_phis(i1 %c, i32 %end) {
; CHECK-LABEL: @live_block_test_switch_loop_phis(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[C:%.*]], label [[CHECK:%.*]], label [[LIVE:%.*]]
; CHECK:       check:
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       live:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[CHECK]] ], [ [[I_2]], [[LIVE]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA]]
;
preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 %c, label %check, label %live

check:
  switch i32 1, label %live [i32 0, label %live
  i32 1, label %backedge
  i32 2, label %live]

live:
  %phi = phi i32 [ 1, %header ], [ -1, %check ], [ -1, %check ], [ -1, %check ]
  %i.2 = add i32 %i, %phi
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %check], [%i.2, %live]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can remove part of blocks of inner loop while the loop still
; preserves, in presence of outer loop.
define i32 @partial_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @partial_sub_loop_test_branch_loop(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @partial_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @partial_sub_loop_test_switch_loop(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  switch i32 1, label %dead [i32 0, label %dead
  i32 1, label %backedge
  i32 2, label %dead]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %header], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  %cmp = icmp slt i32 %i.inc, %end
  br i1 %cmp, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

; Check that we can completely delete inner loop and preserve the outer loop.
define i32 @full_sub_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    br i1 false, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    br i1 false, label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  br i1 false, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  br i1 false, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @full_sub_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    switch i32 1, label [[DEAD:%.*]] [
; CHECK-NEXT:    i32 0, label [[BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    switch i32 1, label [[OUTER_BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[HEADER]]
; CHECK-NEXT:    ]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  switch i32 1, label %dead [i32 0, label %backedge]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  switch i32 1, label %outer_backedge [i32 0, label %header]

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

; Inverted condition in live_part.
define i32 @full_sub_loop_test_branch_loop_inverse_1(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    br i1 false, label [[HEADER]], label [[OUTER_BACKEDGE]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  br i1 false, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @full_sub_loop_test_switch_loop_inverse_1(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    switch i32 1, label [[BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[DEAD:%.*]]
; CHECK-NEXT:    ]
; CHECK:       dead:
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[BACKEDGE]]
; CHECK:       backedge:
; CHECK-NEXT:    [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_1]], 1
; CHECK-NEXT:    switch i32 1, label [[OUTER_BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[HEADER]]
; CHECK-NEXT:    ]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  switch i32 1, label %backedge [i32 0, label %dead]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  switch i32 1, label %outer_backedge [i32 0, label %header]

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @full_sub_loop_test_branch_loop_inverse_2(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_2]], 1
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ poison, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  br i1 false, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  br i1 true, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @full_sub_loop_test_switch_loop_inverse_2(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    [[I_2:%.*]] = add i32 [[I]], 1
; CHECK-NEXT:    [[I_INC]] = add i32 [[I_2]], 1
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ poison, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  switch i32 1, label %dead [i32 0, label %backedge]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  switch i32 1, label %header [i32 0, label %outer_backedge]

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}


define i32 @full_sub_loop_test_branch_loop_inverse_3(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_3(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ poison, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  br i1 true, label %backedge, label %dead

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  br i1 true, label %header, label %outer_backedge

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @full_sub_loop_test_switch_loop_inverse_3(i32 %end) {
; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_3(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
; CHECK:       outer_header:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[OUTER_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       preheader.split:
; CHECK-NEXT:    br label [[HEADER:%.*]]
; CHECK:       header:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[I]], [[I]]
; CHECK-NEXT:    [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT:    br label [[HEADER]]
; CHECK:       outer_backedge:
; CHECK-NEXT:    [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT:    [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT:    br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ poison, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
  br label %outer_header

outer_header:
  %j = phi i32 [0, %entry], [%j.inc, %outer_backedge]
  br label %preheader

preheader:
  br label %header

header:
  %i = phi i32 [0, %preheader], [%i.inc, %backedge]
  br label  %live_part

live_part:
  %mul = mul i32 %i, %i
  switch i32 1, label %backedge [i32 0, label %dead]

dead:
  %i.2 = add i32 %i, 1
  br label %backedge

backedge:
  %i.1 = phi i32 [%i, %live_part], [%i.2, %dead]
  %i.inc = add i32 %i.1, 1
  switch i32 1, label %header [i32 0, label %outer_backedge]

outer_backedge:
  %j.inc = add i32 %j, 1
  %cmp.j = icmp slt i32 %j.inc, %end
  br i1 %cmp.j, label %outer_header, label %exit

exit:
  ret i32 %i.inc
}

define i32 @exit_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @exit_branch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[LOOP_2_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_2.split:
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br label [[LOOP_3]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %loop_1_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 true, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @exit_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @exit_switch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[LOOP_2_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_2.split:
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br label [[LOOP_3]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %loop_1_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  switch i32 1, label %loop_3 [i32 0, label %loop_2_backedge]

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_branch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br i1 false, label %loop_3_backedge, label %loop_1_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_switch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_branch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br i1 false, label %loop_3_backedge, label %loop_2_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i32 %N) {
; CHECK-LABEL: @intermediate_switch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_subloop_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_branch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  br i1 false, label %loop_3_backedge, label %loop_1_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_subloop_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_switch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_subloop_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_branch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  br i1 false, label %loop_3_backedge, label %loop_2_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_subloop_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_subloop_switch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_complex_subloop_branch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_branch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK:       intermediate_loop.backedge:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP]]
; CHECK:       intermediate_block:
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_block

intermediate_block:
  br i1 %cond2, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  br i1 false, label %loop_3_backedge, label %loop_2_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_complex_subloop_switch_from_inner_to_parent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_switch_from_inner_to_parent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK:       intermediate_loop.backedge:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP]]
; CHECK:       intermediate_block:
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    switch i32 1, label [[LOOP_2_BACKEDGE]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_block

intermediate_block:
  br i1 %cond2, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  switch i32 1, label %loop_2_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}


define i32 @intermediate_complex_subloop_branch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_branch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK:       intermediate_loop.backedge:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP]]
; CHECK:       intermediate_block:
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    br i1 false, label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_block

intermediate_block:
  br i1 %cond2, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  br i1 false, label %loop_3_backedge, label %loop_1_backedge

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @intermediate_complex_subloop_switch_from_inner_to_grandparent(i1 %cond1, i1 %cond2, i1 %cond3, i32 %N) {
; CHECK-LABEL: @intermediate_complex_subloop_switch_from_inner_to_grandparent(
; CHECK-NEXT:  preheader:
; CHECK-NEXT:    br label [[LOOP_1:%.*]]
; CHECK:       loop_1:
; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_2:%.*]]
; CHECK:       loop_2:
; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br label [[LOOP_3:%.*]]
; CHECK:       loop_3:
; CHECK-NEXT:    [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[INTERMEDIATE:%.*]]
; CHECK:       intermediate:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP:%.*]]
; CHECK:       intermediate_loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE:%.*]], label [[INTERMEDIATE_BLOCK:%.*]]
; CHECK:       intermediate_loop.backedge:
; CHECK-NEXT:    br label [[INTERMEDIATE_LOOP]]
; CHECK:       intermediate_block:
; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[INTERMEDIATE_LOOP_BACKEDGE]], label [[INTERMEDIATE_EXIT:%.*]]
; CHECK:       intermediate_exit:
; CHECK-NEXT:    switch i32 1, label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] [
; CHECK-NEXT:    i32 0, label [[LOOP_3_BACKEDGE]]
; CHECK-NEXT:    ]
; CHECK:       loop_3_backedge:
; CHECK-NEXT:    [[K_NEXT]] = add i32 [[K]], 1
; CHECK-NEXT:    br i1 [[COND2]], label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
; CHECK:       loop_2_backedge:
; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT:    [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]]
; CHECK:       loop_1_backedge.loopexit:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge.loopexit1:
; CHECK-NEXT:    br label [[LOOP_1_BACKEDGE]]
; CHECK:       loop_1_backedge:
; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
; CHECK-NEXT:    [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
; CHECK-NEXT:    br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ]
; CHECK-NEXT:    ret i32 [[I_LCSSA]]
;
preheader:
  br label %loop_1

loop_1:
  %i = phi i32 [ 0, %preheader ], [ %i.next, %loop_1_backedge ]
  br label %loop_2

loop_2:
  %j = phi i32 [ 0, %loop_1 ], [ %j.next, %loop_2_backedge ]
  br label %loop_3

loop_3:
  %k = phi i32 [ 0, %loop_2 ], [ %k.next, %loop_3_backedge ]
  br i1 %cond1, label %loop_3_backedge, label %intermediate

intermediate:
  br label %intermediate_loop

intermediate_loop:
  br i1 %cond3, label %intermediate_loop, label %intermediate_block

intermediate_block:
  br i1 %cond2, label %intermediate_loop, label %intermediate_exit

intermediate_exit:
  switch i32 1, label %loop_1_backedge [i32 0, label %loop_3_backedge]

loop_3_backedge:
  %k.next = add i32 %k, 1
  br i1 %cond2, label %loop_3, label %loop_2_backedge

loop_2_backedge:
  %j.next = add i32 %j, 1
  %c_2 = icmp slt i32 %j.next, %N
  br i1 %c_2, label %loop_2, label %loop_1_backedge

loop_1_backedge:
  %i.next = add i32 %i, 1
  %c_1 = icmp slt i32 %i.next, %N
  br i1 %c_1, label %loop_1, label %exit

exit:
  ret i32 %i
}

define i32 @complex_dead_subloop_branch(i1 %cond1, i1 %cond2, i1 %cond3) {
; CHECK-LABEL: @complex_dead_subloop_branch(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[RESULT_LCSSA:%.*]] = phi i32 [ 0, [[LOOP]] ]
; CHECK-NEXT:    ret i32 [[RESULT_LCSSA]]
;
entry:
  br label %loop

loop:
  br i1 true, label %latch, label %subloop

subloop:
  br i1 %cond1, label %x, label %y

x:
  br label %subloop_latch

y:
  br label %subloop_latch

subloop_latch:
  %dead_phi = phi i32 [ 1, %x ], [ 2, %y ]
  br i1 %cond2, label %latch, label %subloop

latch:
  %result = phi i32 [ 0, %loop ], [ %dead_phi, %subloop_latch ]
  br i1 %cond3, label %loop, label %exit

exit:
  ret i32 %result
}

define i32 @complex_dead_subloop_switch(i1 %cond1, i1 %cond2, i1 %cond3) {
; CHECK-LABEL: @complex_dead_subloop_switch(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 [[COND3:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    [[RESULT_LCSSA:%.*]] = phi i32 [ 0, [[LOOP]] ]
; CHECK-NEXT:    ret i32 [[RESULT_LCSSA]]
;
entry:
  br label %loop

loop:
  switch i32 1, label %latch [ i32 0, label %subloop ]

subloop:
  br i1 %cond1, label %x, label %y

x:
  br label %subloop_latch

y:
  br label %subloop_latch

subloop_latch:
  %dead_phi = phi i32 [ 1, %x ], [ 2, %y ]
  br i1 %cond2, label %latch, label %subloop

latch:
  %result = phi i32 [ 0, %loop ], [ %dead_phi, %subloop_latch ]
  br i1 %cond3, label %loop, label %exit

exit:
  ret i32 %result
}

define void @test_crash_01() {
; CHECK-LABEL: @test_crash_01(
; CHECK-NEXT:  bb:
; CHECK-NEXT:    br label [[BB1:%.*]]
; CHECK:       bb1:
; CHECK-NEXT:    br i1 undef, label [[BB17:%.*]], label [[BB2:%.*]]
; CHECK:       bb2:
; CHECK-NEXT:    switch i32 0, label [[BB2_SPLIT:%.*]] [
; CHECK-NEXT:    i32 1, label [[BB19:%.*]]
; CHECK-NEXT:    ]
; CHECK:       bb2.split:
; CHECK-NEXT:    br label [[BB3:%.*]]
; CHECK:       bb3:
; CHECK-NEXT:    switch i32 undef, label [[BB16:%.*]] [
; CHECK-NEXT:    i32 0, label [[BB15:%.*]]
; CHECK-NEXT:    i32 1, label [[BB14:%.*]]
; CHECK-NEXT:    i32 2, label [[BB13:%.*]]
; CHECK-NEXT:    i32 3, label [[BB12:%.*]]
; CHECK-NEXT:    i32 4, label [[BB11:%.*]]
; CHECK-NEXT:    i32 5, label [[BB8:%.*]]
; CHECK-NEXT:    i32 6, label [[BB10:%.*]]
; CHECK-NEXT:    i32 7, label [[BB9:%.*]]
; CHECK-NEXT:    i32 8, label [[BB7:%.*]]
; CHECK-NEXT:    ]
; CHECK:       bb7:
; CHECK-NEXT:    unreachable
; CHECK:       bb8:
; CHECK-NEXT:    switch i32 undef, label [[BB28:%.*]] [
; CHECK-NEXT:    i32 0, label [[BB27:%.*]]
; CHECK-NEXT:    i32 1, label [[BB26:%.*]]
; CHECK-NEXT:    i32 2, label [[BB23:%.*]]
; CHECK-NEXT:    i32 3, label [[BB24:%.*]]
; CHECK-NEXT:    i32 4, label [[BB25:%.*]]
; CHECK-NEXT:    i32 5, label [[BB29:%.*]]
; CHECK-NEXT:    i32 6, label [[BB22:%.*]]
; CHECK-NEXT:    i32 7, label [[BB20:%.*]]
; CHECK-NEXT:    i32 8, label [[BB21:%.*]]
; CHECK-NEXT:    ]
; CHECK:       bb9:
; CHECK-NEXT:    unreachable
; CHECK:       bb10:
; CHECK-NEXT:    unreachable
; CHECK:       bb11:
; CHECK-NEXT:    br label [[BB8]]
; CHECK:       bb12:
; CHECK-NEXT:    unreachable
; CHECK:       bb13:
; CHECK-NEXT:    unreachable
; CHECK:       bb14:
; CHECK-NEXT:    unreachable
; CHECK:       bb15:
; CHECK-NEXT:    unreachable
; CHECK:       bb16:
; CHECK-NEXT:    unreachable
; CHECK:       bb17:
; CHECK-NEXT:    ret void
; CHECK:       bb19:
; CHECK-NEXT:    ret void
; CHECK:       bb20:
; CHECK-NEXT:    unreachable
; CHECK:       bb21:
; CHECK-NEXT:    unreachable
; CHECK:       bb22:
; CHECK-NEXT:    unreachable
; CHECK:       bb23:
; CHECK-NEXT:    unreachable
; CHECK:       bb24:
; CHECK-NEXT:    unreachable
; CHECK:       bb25:
; CHECK-NEXT:    unreachable
; CHECK:       bb26:
; CHECK-NEXT:    unreachable
; CHECK:       bb27:
; CHECK-NEXT:    unreachable
; CHECK:       bb28:
; CHECK-NEXT:    unreachable
; CHECK:       bb29:
; CHECK-NEXT:    br label [[BB3]]
;
bb:
  br label %bb1

bb1:                                              ; preds = %bb
  br i1 undef, label %bb17, label %bb2

bb2:                                              ; preds = %bb1
  br label %bb3

bb3:                                              ; preds = %bb6, %bb2
  br label %bb4

bb4:                                              ; preds = %bb3
  switch i32 0, label %bb5 [
  i32 1, label %bb19
  i32 2, label %bb18
  ]

bb5:                                              ; preds = %bb4
  switch i32 undef, label %bb16 [
  i32 0, label %bb15
  i32 1, label %bb14
  i32 2, label %bb13
  i32 3, label %bb12
  i32 4, label %bb11
  i32 5, label %bb8
  i32 6, label %bb10
  i32 7, label %bb9
  i32 8, label %bb7
  ]

bb6:                                              ; preds = %bb29, %bb18
  br label %bb3

bb7:                                              ; preds = %bb5
  unreachable

bb8:                                              ; preds = %bb11, %bb5
  switch i32 undef, label %bb28 [
  i32 0, label %bb27
  i32 1, label %bb26
  i32 2, label %bb23
  i32 3, label %bb24
  i32 4, label %bb25
  i32 5, label %bb29
  i32 6, label %bb22
  i32 7, label %bb20
  i32 8, label %bb21
  ]

bb9:                                              ; preds = %bb5
  unreachable

bb10:                                             ; preds = %bb5
  unreachable

bb11:                                             ; preds = %bb5
  br label %bb8

bb12:                                             ; preds = %bb5
  unreachable

bb13:                                             ; preds = %bb5
  unreachable

bb14:                                             ; preds = %bb5
  unreachable

bb15:                                             ; preds = %bb5
  unreachable

bb16:                                             ; preds = %bb5
  unreachable

bb17:                                             ; preds = %bb1
  ret void

bb18:                                             ; preds = %bb4
  br label %bb6

bb19:                                             ; preds = %bb4
  ret void

bb20:                                             ; preds = %bb8
  unreachable

bb21:                                             ; preds = %bb8
  unreachable

bb22:                                             ; preds = %bb8
  unreachable

bb23:                                             ; preds = %bb8
  unreachable

bb24:                                             ; preds = %bb8
  unreachable

bb25:                                             ; preds = %bb8
  unreachable

bb26:                                             ; preds = %bb8
  unreachable

bb27:                                             ; preds = %bb8
  unreachable

bb28:                                             ; preds = %bb8
  unreachable

bb29:                                             ; preds = %bb8
  br label %bb6
}
